Process each sorted sample

pathway <- "/Users/rhalenathomas/Documents/Data/scRNAseq/PhenoID/scRNAseqSorted/objs/"

Neurons1 <- readRDS(paste(pathway,"seu1.rds",sep = ""))
Neurons2 <- readRDS(paste(pathway,"seu2.rds",sep = ""))
Glia1 <- readRDS(paste(pathway,"seu3.rds",sep = ""))
Glia2 <- readRDS(paste(pathway,"seu4.rds",sep = ""))

Neurons1
An object of class Seurat 
33541 features across 3952 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO
Neurons2
An object of class Seurat 
33541 features across 34830 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO
Glia1   #-Astrocytes
An object of class Seurat 
33541 features across 54723 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO
Glia2   #-Radial Glia
An object of class Seurat 
33541 features across 10338 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO

Check QC

library(Seurat)

VlnPlot(Neurons1, pt.size = 0.10, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)

VlnPlot(Neurons1, pt.size = 0.10, features = c("nFeature_RNA"), y.max = 1000)
Warning: Removed 555 rows containing non-finite values (stat_ydensity).
Warning: Removed 555 rows containing missing values (geom_point).

VlnPlot(Neurons2, pt.size = 0.10, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)

VlnPlot(Glia1, pt.size = 0.10, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)

VlnPlot(Glia2, pt.size = 0.10, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)

NA
NA
NA

Filter


Neuron1.ft <- subset(Neurons1, subset = nFeature_RNA > 250 & nCount_RNA < 10000)


Neuron2.ft <- subset(Neurons2, subset = nFeature_RNA > 350 & nCount_RNA > 250 & nCount_RNA < 10000) 


Glia1.ft <- subset(Glia1, subset = nFeature_RNA > 500 & nCount_RNA > 500 & nCount_RNA < 10000) 


Glia2.ft <- subset(Glia2, subset = nFeature_RNA > 300 & nCount_RNA > 500 & nCount_RNA < 10000) 


Neuron1.ft
An object of class Seurat 
33541 features across 1833 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO
Neuron2.ft
An object of class Seurat 
33541 features across 10162 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO
Glia1.ft
An object of class Seurat 
33541 features across 37813 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO
Glia2.ft
An object of class Seurat 
33541 features across 5000 samples within 2 assays 
Active assay: RNA (33538 features, 0 variable features)
 1 other assay present: HTO

Remove doublets from each Sorted population

suppressMessages(require(DoubletFinder))
# Neurons1
seu.d <- Neuron1.ft
seu.d <- NormalizeData(seu.d)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
seu.d = FindVariableFeatures(seu.d, verbose = F)
seu.d = ScaleData(seu.d, vars.to.regress = c("nFeature_RNA", "percent.mt"),
    verbose = F)
seu.d = RunPCA(seu.d, verbose = F, npcs = 20)
seu.d = RunUMAP(seu.d, dims = 1:10, verbose = F)

# starts with 1833 cells 
nExp <- round(ncol(seu.d) * 0.013)  # expect close to 1.3doublets
seu.d <- doubletFinder_v3(seu.d, pN = 0.25, pK = 0.09, nExp = nExp, PCs = 1:10)
[1] "Creating 611 artificial doublets..."
[1] "Creating Seurat object..."
[1] "Normalizing Seurat object..."
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Finding variable genes..."
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Scaling data..."
Centering and scaling data matrix

  |                                                                                            
  |                                                                                      |   0%
  |                                                                                            
  |===========================================                                           |  50%
  |                                                                                            
  |======================================================================================| 100%
[1] "Running PCA..."
[1] "Calculating PC distance matrix..."
[1] "Computing pANN..."
[1] "Classifying doublets.."
# name of the DF prediction can change, so extract the correct column name.
DF.name = colnames(seu.d@meta.data)[grepl("DF.classification", colnames(seu.d@meta.data))]
seu.d <- seu.d[, seu.d@meta.data[, DF.name]== "Singlet"]
dim(seu.d)
[1] 33538  1809
Neurons1 <- seu.d
# Neurons2
seu.d <- Neuron2.ft  # starting 10162 cells
seu.d <- NormalizeData(seu.d)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
seu.d = FindVariableFeatures(seu.d, verbose = F)
seu.d = ScaleData(seu.d, vars.to.regress = c("nFeature_RNA", "percent.mt"),
    verbose = F)
seu.d = RunPCA(seu.d, verbose = F, npcs = 20)
seu.d = RunUMAP(seu.d, dims = 1:10, verbose = F)

nExp <- round(ncol(seu.d) * 0.076)  # expect 7.6% doublets for 
seu.d <- doubletFinder_v3(seu.d, pN = 0.25, pK = 0.09, nExp = nExp, PCs = 1:10)
[1] "Creating 3387 artificial doublets..."
[1] "Creating Seurat object..."
[1] "Normalizing Seurat object..."
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Finding variable genes..."
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Scaling data..."
Centering and scaling data matrix

  |                                                                                            
  |                                                                                      |   0%
  |                                                                                            
  |===========================================                                           |  50%
  |                                                                                            
  |======================================================================================| 100%
[1] "Running PCA..."
[1] "Calculating PC distance matrix..."
[1] "Computing pANN..."
[1] "Classifying doublets.."
# name of the DF prediction can change, so extract the correct column name.
DF.name = colnames(seu.d@meta.data)[grepl("DF.classification", colnames(seu.d@meta.data))]
seu.d <- seu.d[, seu.d@meta.data[, DF.name]== "Singlet"]
dim(seu.d)
[1] 33538  9390
Neurons2 <- seu.d

Astrocytes has too many cells Demultiplex with hashtags


DefaultAssay(Glia1.ft) <- 'HTO'
ht <- HTODemux(Glia1.ft, positive.quantile = 0.98)
Warning in PseudobulkExpression(object = object, pb.method = "average",  :
  Exponentiation yielded infinite values. `data` may not be log-normed.
Cutoff for B0251-TotalSeqB : 78 reads
Cutoff for B0252-TotalSeqB : 92 reads
Cutoff for B0256-TotalSeqB : 1 reads
table(ht$HTO_classification.global)

 Doublet Negative  Singlet 
    3812    25323     8678 
table(ht$HTO_classification)

                B0251-TotalSeqB B0251-TotalSeqB_B0251-TotalSeqB B0251-TotalSeqB_B0252-TotalSeqB 
                           4654                              46                            3766 
                B0252-TotalSeqB                        Negative 
                           4024                           25323 
table(ht$hash.ID)

        Doublet B0252-TotalSeqB        Negative B0251-TotalSeqB 
           3812            4024           25323            4654 
RidgePlot(ht, assay = "HTO", group.by = "HTO_maxID", features = rownames(ht[["HTO"]]), log = TRUE)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the
existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the
existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the
existing scale.
Picking joint bandwidth of 0.028
Picking joint bandwidth of 0.0257
Picking joint bandwidth of 0.000306

# perhaps I put the wrong hashtags in the compute canada pipeline

VlnPlot(ht, assay = "RNA", group.by = 'hash.ID', features = "nFeature_RNA")


# one of the replicates isn't represented labelled or not recognize well
# I'll select the two reps with clear hashtags


Idents(ht) <- 'hash.ID'
glia1.temp <- subset(ht, idents = c("B0252-TotalSeqB","B0251-TotalSeqB"))
dim(glia1.temp)
[1]    3 8678

In this case some doublets will already be removed

# Glia 1 astrocytes  8678 cells

DefaultAssay(glia1.temp) <- "RNA"
seu.d <- glia1.temp
seu.d <- NormalizeData(seu.d)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
seu.d = FindVariableFeatures(seu.d, verbose = F)
seu.d = ScaleData(seu.d, vars.to.regress = c("nFeature_RNA", "percent.mt"),
    verbose = F)
seu.d = RunPCA(seu.d, verbose = F, npcs = 20)
seu.d = RunUMAP(seu.d, dims = 1:10, verbose = F)

nExp <- round(ncol(seu.d) * 0.064)  # expect 6.4% doublets input of 13000 cells
seu.d <- doubletFinder_v3(seu.d, pN = 0.25, pK = 0.09, nExp = nExp, PCs = 1:10)
[1] "Creating 2893 artificial doublets..."
[1] "Creating Seurat object..."
[1] "Normalizing Seurat object..."
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Finding variable genes..."
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Scaling data..."
Centering and scaling data matrix

  |                                                                                            
  |                                                                                      |   0%
  |                                                                                            
  |===========================================                                           |  50%
  |                                                                                            
  |======================================================================================| 100%
[1] "Running PCA..."
[1] "Calculating PC distance matrix..."
[1] "Computing pANN..."
[1] "Classifying doublets.."
# name of the DF prediction can change, so extract the correct column name.
DF.name = colnames(seu.d@meta.data)[grepl("DF.classification", colnames(seu.d@meta.data))]
seu.d <- seu.d[, seu.d@meta.data[, DF.name]== "Singlet"]
dim(seu.d)
[1] 33538  8123
Astrocytes <- seu.d

Glia2 - Radial Glia, low CD44 in the FACS sort.


seu.d <- Glia2.ft   # 5000 cells 
seu.d <- NormalizeData(seu.d)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
seu.d = FindVariableFeatures(seu.d, verbose = F)
seu.d = ScaleData(seu.d, vars.to.regress = c("nFeature_RNA", "percent.mt"),
    verbose = F)
seu.d = RunPCA(seu.d, verbose = F, npcs = 20)
seu.d = RunUMAP(seu.d, dims = 1:10, verbose = F)

nExp <- round(ncol(seu.d) * 0.039)  # expect 6% doublets 5000 cells 
seu.d <- doubletFinder_v3(seu.d, pN = 0.25, pK = 0.09, nExp = nExp, PCs = 1:10)
[1] "Creating 1667 artificial doublets..."
[1] "Creating Seurat object..."
[1] "Normalizing Seurat object..."
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Finding variable genes..."
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Scaling data..."
Centering and scaling data matrix

  |                                                                                            
  |                                                                                      |   0%
  |                                                                                            
  |===========================================                                           |  50%
  |                                                                                            
  |======================================================================================| 100%
[1] "Running PCA..."
[1] "Calculating PC distance matrix..."
[1] "Computing pANN..."
[1] "Classifying doublets.."
# name of the DF prediction can change, so extract the correct column name.
DF.name = colnames(seu.d@meta.data)[grepl("DF.classification", colnames(seu.d@meta.data))]
seu.d <- seu.d[, seu.d@meta.data[, DF.name]== "Singlet"]
dim(seu.d)
[1] 33538  4805
RadialGlia <- seu.d

Annotate the cell types in each Flow population

Rename Idents to prepare to merge

unique(sorted.merge$orig.ident)
[1] "Neurons1"   "Neurons2"   "Astroctyes" "RadialGlia"

Cluster merge object

seu <- RunUMAP(seu, dim = 1:18, n.neighbors = 43)
21:59:45 UMAP embedding parameters a = 0.9922 b = 1.112
21:59:45 Read 7809 rows and found 18 numeric columns
21:59:45 Using Annoy for neighbor search, n_neighbors = 43
21:59:45 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
21:59:45 Writing NN index file to temp file /var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T//Rtmp0GH9mR/file1304393f0b75
21:59:46 Searching Annoy index using 1 thread, search_k = 4300
21:59:48 Annoy recall = 100%
21:59:48 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 43
21:59:49 Initializing from normalized Laplacian + noise (using irlba)
21:59:49 Commencing optimization for 500 epochs, with 480674 positive edges
Using method 'umap'
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
22:00:03 Optimization finished
DimPlot(seu, reduction = "umap")

Quick annotation from previously annotated

NOTE TO ME *******

I will need to look through the pre - filtering cells - neurons 1 is the same

Possible just down sample astro so the numbers are the same. The other samples were randomly downsampled. Maybe if I repeat the down sampling with different seeds I’ll get results more similar. Also if I cluster before down sampling like I did the first time.

Calculate proprotion in object in the figures:

table(seu.L$orig.ident)

  Neurons1   Neurons2 Astrocytes RadialGlia 
      1723       2000       3000       2000 
table(seu.L$orig.ident, seu.L$Cell_Subtype_Markers)
            
             Astrocytes-HPD Neurons-ASCL1 RadialGlia-RPL41 Neurons-SPARCL1 Astrocytes-COL3A1
  Neurons1                8             2               10             564                 0
  Neurons2               72           784              172               0                 5
  Astrocytes           1535            11               48               0               747
  RadialGlia            175            57              587               0               207
            
             Neurons-TFPI1 RadialGlia-PTN Neurons-CP Astrocytes-FABP5 Neurons-MGP
  Neurons1               5            112        333                5           0
  Neurons2             302             53          0                3         237
  Astrocytes            55             45          0              324          72
  RadialGlia            53            441          0                1          17
            
             RadialGlia-NEAT1 DANeurons-RAB3B Neurons-GRIA2  Mix  NPC Neurons-TPH1
  Neurons1                  4             131           245   15  140            4
  Neurons2                 24              76             0   84    6          105
  Astrocytes               35               0             0   81    3            4
  RadialGlia              241              52             0   48    5           20
            
             DANeurons-TPBG DANeurons-TTR RadialGlia-CY1B1 RadialGlia-TOP2A RadialGlia-VCAN
  Neurons1               10            65               57               12               1
  Neurons2               50            20                0                7               0
  Astrocytes              7             0                0               18              15
  RadialGlia             46            19                0                8              23

Figure 6 F

pdf(paste(output_path,"BarChartProportionCellTypesin4popsNov2.pdf"), height = 5, width = 8)
ggplot(df, aes(x = FACpop, y = Freq, fill = Cell_subtypes)) + 
  geom_col(position = "fill") + theme_classic() +
  scale_fill_manual(values = clust.colours) +
  #scale_x_discrete(expand = c(0, 0)) +
  scale_y_continuous(expand = c(0,0)) +
  theme(axis.text.x = element_text(angle = 90, size = 16), axis.text.y = element_text(size = 16)) +
  labs(y = "Proportion of Cells", x = "") +
  theme(axis.title.y = element_text(size = 16), legend.text = element_text(size = 16), legend.title = element_text(size = 16)) 
dev.off()
null device 
          1 
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKClByb2Nlc3MgZWFjaCBzb3J0ZWQgc2FtcGxlCgpgYGB7cn0KcGF0aHdheSA8LSAiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvUGhlbm9JRC9zY1JOQXNlcVNvcnRlZC9vYmpzLyIKCk5ldXJvbnMxIDwtIHJlYWRSRFMocGFzdGUocGF0aHdheSwic2V1MS5yZHMiLHNlcCA9ICIiKSkKTmV1cm9uczIgPC0gcmVhZFJEUyhwYXN0ZShwYXRod2F5LCJzZXUyLnJkcyIsc2VwID0gIiIpKQpHbGlhMSA8LSByZWFkUkRTKHBhc3RlKHBhdGh3YXksInNldTMucmRzIixzZXAgPSAiIikpCkdsaWEyIDwtIHJlYWRSRFMocGFzdGUocGF0aHdheSwic2V1NC5yZHMiLHNlcCA9ICIiKSkKCk5ldXJvbnMxCk5ldXJvbnMyCkdsaWExICAgIy1Bc3Ryb2N5dGVzCkdsaWEyICAgIy1SYWRpYWwgR2xpYQoKCmBgYAoKQ2hlY2sgUUMKCmBgYHtyfQpsaWJyYXJ5KFNldXJhdCkKClZsblBsb3QoTmV1cm9uczEsIHB0LnNpemUgPSAwLjEwLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubXQiKSwgbmNvbCA9IDMpClZsblBsb3QoTmV1cm9uczEsIHB0LnNpemUgPSAwLjEwLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIpLCB5Lm1heCA9IDEwMDApClZsblBsb3QoTmV1cm9uczIsIHB0LnNpemUgPSAwLjEwLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubXQiKSwgbmNvbCA9IDMpClZsblBsb3QoR2xpYTEsIHB0LnNpemUgPSAwLjEwLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubXQiKSwgbmNvbCA9IDMpClZsblBsb3QoR2xpYTIsIHB0LnNpemUgPSAwLjEwLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubXQiKSwgbmNvbCA9IDMpCgoKCmBgYAoKCgpGaWx0ZXIKCmBgYHtyfQoKTmV1cm9uMS5mdCA8LSBzdWJzZXQoTmV1cm9uczEsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDI1MCAmIG5Db3VudF9STkEgPCAxMDAwMCkKCgpOZXVyb24yLmZ0IDwtIHN1YnNldChOZXVyb25zMiwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gMzUwICYgbkNvdW50X1JOQSA+IDI1MCAmIG5Db3VudF9STkEgPCAxMDAwMCkgCgoKR2xpYTEuZnQgPC0gc3Vic2V0KEdsaWExLCBzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiA1MDAgJiBuQ291bnRfUk5BID4gNTAwICYgbkNvdW50X1JOQSA8IDEwMDAwKSAKCgpHbGlhMi5mdCA8LSBzdWJzZXQoR2xpYTIsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDMwMCAmIG5Db3VudF9STkEgPiA1MDAgJiBuQ291bnRfUk5BIDwgMTAwMDApIAoKCk5ldXJvbjEuZnQKTmV1cm9uMi5mdApHbGlhMS5mdApHbGlhMi5mdAoKCmBgYAoKUmVtb3ZlIGRvdWJsZXRzIGZyb20gZWFjaCBTb3J0ZWQgcG9wdWxhdGlvbgoKYGBge3J9CnN1cHByZXNzTWVzc2FnZXMocmVxdWlyZShEb3VibGV0RmluZGVyKSkKCmBgYAoKCgoKYGBge3J9CiMgTmV1cm9uczEKc2V1LmQgPC0gTmV1cm9uMS5mdApzZXUuZCA8LSBOb3JtYWxpemVEYXRhKHNldS5kKQpzZXUuZCA9IEZpbmRWYXJpYWJsZUZlYXR1cmVzKHNldS5kLCB2ZXJib3NlID0gRikKc2V1LmQgPSBTY2FsZURhdGEoc2V1LmQsIHZhcnMudG8ucmVncmVzcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJwZXJjZW50Lm10IiksCiAgICB2ZXJib3NlID0gRikKc2V1LmQgPSBSdW5QQ0Eoc2V1LmQsIHZlcmJvc2UgPSBGLCBucGNzID0gMjApCnNldS5kID0gUnVuVU1BUChzZXUuZCwgZGltcyA9IDE6MTAsIHZlcmJvc2UgPSBGKQoKIyBzdGFydHMgd2l0aCAxODMzIGNlbGxzIApuRXhwIDwtIHJvdW5kKG5jb2woc2V1LmQpICogMC4wMTMpICAjIGV4cGVjdCBjbG9zZSB0byAxLjNkb3VibGV0cwpzZXUuZCA8LSBkb3VibGV0RmluZGVyX3YzKHNldS5kLCBwTiA9IDAuMjUsIHBLID0gMC4wOSwgbkV4cCA9IG5FeHAsIFBDcyA9IDE6MTApCgoKIyBuYW1lIG9mIHRoZSBERiBwcmVkaWN0aW9uIGNhbiBjaGFuZ2UsIHNvIGV4dHJhY3QgdGhlIGNvcnJlY3QgY29sdW1uIG5hbWUuCkRGLm5hbWUgPSBjb2xuYW1lcyhzZXUuZEBtZXRhLmRhdGEpW2dyZXBsKCJERi5jbGFzc2lmaWNhdGlvbiIsIGNvbG5hbWVzKHNldS5kQG1ldGEuZGF0YSkpXQpzZXUuZCA8LSBzZXUuZFssIHNldS5kQG1ldGEuZGF0YVssIERGLm5hbWVdPT0gIlNpbmdsZXQiXQpkaW0oc2V1LmQpCgpOZXVyb25zMSA8LSBzZXUuZAoKCmBgYAoKYGBge3J9CiMgTmV1cm9uczIKc2V1LmQgPC0gTmV1cm9uMi5mdCAgIyBzdGFydGluZyAxMDE2MiBjZWxscwpzZXUuZCA8LSBOb3JtYWxpemVEYXRhKHNldS5kKQpzZXUuZCA9IEZpbmRWYXJpYWJsZUZlYXR1cmVzKHNldS5kLCB2ZXJib3NlID0gRikKc2V1LmQgPSBTY2FsZURhdGEoc2V1LmQsIHZhcnMudG8ucmVncmVzcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJwZXJjZW50Lm10IiksCiAgICB2ZXJib3NlID0gRikKc2V1LmQgPSBSdW5QQ0Eoc2V1LmQsIHZlcmJvc2UgPSBGLCBucGNzID0gMjApCnNldS5kID0gUnVuVU1BUChzZXUuZCwgZGltcyA9IDE6MTAsIHZlcmJvc2UgPSBGKQoKbkV4cCA8LSByb3VuZChuY29sKHNldS5kKSAqIDAuMDc2KSAgIyBleHBlY3QgNy42JSBkb3VibGV0cyBmb3IgCnNldS5kIDwtIGRvdWJsZXRGaW5kZXJfdjMoc2V1LmQsIHBOID0gMC4yNSwgcEsgPSAwLjA5LCBuRXhwID0gbkV4cCwgUENzID0gMToxMCkKCgojIG5hbWUgb2YgdGhlIERGIHByZWRpY3Rpb24gY2FuIGNoYW5nZSwgc28gZXh0cmFjdCB0aGUgY29ycmVjdCBjb2x1bW4gbmFtZS4KREYubmFtZSA9IGNvbG5hbWVzKHNldS5kQG1ldGEuZGF0YSlbZ3JlcGwoIkRGLmNsYXNzaWZpY2F0aW9uIiwgY29sbmFtZXMoc2V1LmRAbWV0YS5kYXRhKSldCnNldS5kIDwtIHNldS5kWywgc2V1LmRAbWV0YS5kYXRhWywgREYubmFtZV09PSAiU2luZ2xldCJdCmRpbShzZXUuZCkKCk5ldXJvbnMyIDwtIHNldS5kCgpgYGAKCkFzdHJvY3l0ZXMgaGFzIHRvbyBtYW55IGNlbGxzIERlbXVsdGlwbGV4IHdpdGggaGFzaHRhZ3MKCmBgYHtyfQoKRGVmYXVsdEFzc2F5KEdsaWExLmZ0KSA8LSAnSFRPJwpodCA8LSBIVE9EZW11eChHbGlhMS5mdCwgcG9zaXRpdmUucXVhbnRpbGUgPSAwLjk4KQp0YWJsZShodCRIVE9fY2xhc3NpZmljYXRpb24uZ2xvYmFsKQp0YWJsZShodCRIVE9fY2xhc3NpZmljYXRpb24pCnRhYmxlKGh0JGhhc2guSUQpClJpZGdlUGxvdChodCwgYXNzYXkgPSAiSFRPIiwgZ3JvdXAuYnkgPSAiSFRPX21heElEIiwgZmVhdHVyZXMgPSByb3duYW1lcyhodFtbIkhUTyJdXSksIGxvZyA9IFRSVUUpCiMgcGVyaGFwcyBJIHB1dCB0aGUgd3JvbmcgaGFzaHRhZ3MgaW4gdGhlIGNvbXB1dGUgY2FuYWRhIHBpcGVsaW5lCgpWbG5QbG90KGh0LCBhc3NheSA9ICJSTkEiLCBncm91cC5ieSA9ICdoYXNoLklEJywgZmVhdHVyZXMgPSAibkZlYXR1cmVfUk5BIikKCiMgb25lIG9mIHRoZSByZXBsaWNhdGVzIGlzbid0IHJlcHJlc2VudGVkIGxhYmVsbGVkIG9yIG5vdCByZWNvZ25pemUgd2VsbAojIEknbGwgc2VsZWN0IHRoZSB0d28gcmVwcyB3aXRoIGNsZWFyIGhhc2h0YWdzCgoKSWRlbnRzKGh0KSA8LSAnaGFzaC5JRCcKZ2xpYTEudGVtcCA8LSBzdWJzZXQoaHQsIGlkZW50cyA9IGMoIkIwMjUyLVRvdGFsU2VxQiIsIkIwMjUxLVRvdGFsU2VxQiIpKQpkaW0oZ2xpYTEudGVtcCkKCgoKCmBgYAoKCgpJbiB0aGlzIGNhc2Ugc29tZSBkb3VibGV0cyB3aWxsIGFscmVhZHkgYmUgcmVtb3ZlZAoKYGBge3J9CiMgR2xpYSAxIGFzdHJvY3l0ZXMgIDg2NzggY2VsbHMKCkRlZmF1bHRBc3NheShnbGlhMS50ZW1wKSA8LSAiUk5BIgpzZXUuZCA8LSBnbGlhMS50ZW1wCnNldS5kIDwtIE5vcm1hbGl6ZURhdGEoc2V1LmQpCnNldS5kID0gRmluZFZhcmlhYmxlRmVhdHVyZXMoc2V1LmQsIHZlcmJvc2UgPSBGKQpzZXUuZCA9IFNjYWxlRGF0YShzZXUuZCwgdmFycy50by5yZWdyZXNzID0gYygibkZlYXR1cmVfUk5BIiwgInBlcmNlbnQubXQiKSwKICAgIHZlcmJvc2UgPSBGKQpzZXUuZCA9IFJ1blBDQShzZXUuZCwgdmVyYm9zZSA9IEYsIG5wY3MgPSAyMCkKc2V1LmQgPSBSdW5VTUFQKHNldS5kLCBkaW1zID0gMToxMCwgdmVyYm9zZSA9IEYpCgpuRXhwIDwtIHJvdW5kKG5jb2woc2V1LmQpICogMC4wNjQpICAjIGV4cGVjdCA2LjQlIGRvdWJsZXRzIGlucHV0IG9mIDEzMDAwIGNlbGxzCnNldS5kIDwtIGRvdWJsZXRGaW5kZXJfdjMoc2V1LmQsIHBOID0gMC4yNSwgcEsgPSAwLjA5LCBuRXhwID0gbkV4cCwgUENzID0gMToxMCkKCgojIG5hbWUgb2YgdGhlIERGIHByZWRpY3Rpb24gY2FuIGNoYW5nZSwgc28gZXh0cmFjdCB0aGUgY29ycmVjdCBjb2x1bW4gbmFtZS4KREYubmFtZSA9IGNvbG5hbWVzKHNldS5kQG1ldGEuZGF0YSlbZ3JlcGwoIkRGLmNsYXNzaWZpY2F0aW9uIiwgY29sbmFtZXMoc2V1LmRAbWV0YS5kYXRhKSldCnNldS5kIDwtIHNldS5kWywgc2V1LmRAbWV0YS5kYXRhWywgREYubmFtZV09PSAiU2luZ2xldCJdCmRpbShzZXUuZCkKCkFzdHJvY3l0ZXMgPC0gc2V1LmQKCmBgYAoKR2xpYTIgLSBSYWRpYWwgR2xpYSwgbG93IENENDQgaW4gdGhlIEZBQ1Mgc29ydC4KCmBgYHtyfQoKc2V1LmQgPC0gR2xpYTIuZnQgICAjIDUwMDAgY2VsbHMgCnNldS5kIDwtIE5vcm1hbGl6ZURhdGEoc2V1LmQpCnNldS5kID0gRmluZFZhcmlhYmxlRmVhdHVyZXMoc2V1LmQsIHZlcmJvc2UgPSBGKQpzZXUuZCA9IFNjYWxlRGF0YShzZXUuZCwgdmFycy50by5yZWdyZXNzID0gYygibkZlYXR1cmVfUk5BIiwgInBlcmNlbnQubXQiKSwKICAgIHZlcmJvc2UgPSBGKQpzZXUuZCA9IFJ1blBDQShzZXUuZCwgdmVyYm9zZSA9IEYsIG5wY3MgPSAyMCkKc2V1LmQgPSBSdW5VTUFQKHNldS5kLCBkaW1zID0gMToxMCwgdmVyYm9zZSA9IEYpCgpuRXhwIDwtIHJvdW5kKG5jb2woc2V1LmQpICogMC4wMzkpICAjIGV4cGVjdCA2JSBkb3VibGV0cyA1MDAwIGNlbGxzIApzZXUuZCA8LSBkb3VibGV0RmluZGVyX3YzKHNldS5kLCBwTiA9IDAuMjUsIHBLID0gMC4wOSwgbkV4cCA9IG5FeHAsIFBDcyA9IDE6MTApCgoKIyBuYW1lIG9mIHRoZSBERiBwcmVkaWN0aW9uIGNhbiBjaGFuZ2UsIHNvIGV4dHJhY3QgdGhlIGNvcnJlY3QgY29sdW1uIG5hbWUuCkRGLm5hbWUgPSBjb2xuYW1lcyhzZXUuZEBtZXRhLmRhdGEpW2dyZXBsKCJERi5jbGFzc2lmaWNhdGlvbiIsIGNvbG5hbWVzKHNldS5kQG1ldGEuZGF0YSkpXQpzZXUuZCA8LSBzZXUuZFssIHNldS5kQG1ldGEuZGF0YVssIERGLm5hbWVdPT0gIlNpbmdsZXQiXQpkaW0oc2V1LmQpCgpSYWRpYWxHbGlhIDwtIHNldS5kCgpgYGAKCgpBbm5vdGF0ZSB0aGUgY2VsbCB0eXBlcyBpbiBlYWNoIEZsb3cgcG9wdWxhdGlvbgoKYGBge3J9CgojIE5ldXJvbnMgMQpzZXUgPC0gTm9ybWFsaXplRGF0YShOZXVyb25zMSwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgc2NhbGUuZmFjdG9yID0gMTAwMDApCklkZW50cyhzZXUpIDwtICdvcmlnLmlkZW50JwpzZXUkb3JpZy5pZGVudCA8LSAnTmV1cm9uczEnCmRpbShzZXUpCgpzZXUgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoc2V1LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCnNldSA8LSBTY2FsZURhdGEoc2V1KQpzZXUgPC0gUnVuUENBKHNldSkKc2V1IDwtIFJ1blVNQVAoc2V1LCByZWR1Y3Rpb24gPSAicGNhIiwgbi5uZWlnaGJvcnMgPSA0MywgZGltcyA9IDE6MzApCkRpbVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIpCgoKCgpgYGAKCgoKCgoKClJlbmFtZSBJZGVudHMgdG8gcHJlcGFyZSB0byBtZXJnZQoKCmBgYHtyfQoKSWRlbnRzKE5ldXJvbnMxKSA8LSAnb3JpZy5pZGVudCcKTmV1cm9uczEkb3JpZy5pZGVudCA8LSAnTmV1cm9uczEnCgoKSWRlbnRzKE5ldXJvbnMyKSA8LSAnb3JpZy5pZGVudCcKTmV1cm9uczIkb3JpZy5pZGVudCA8LSAnTmV1cm9uczInCgpJZGVudHMoQXN0cm9jeXRlcykgPC0gJ29yaWcuaWRlbnQnCkFzdHJvY3l0ZXMkb3JpZy5pZGVudCA8LSAnQXN0cm9jdHllcycKSWRlbnRzKFJhZGlhbEdsaWEpIDwtICdvcmlnLmlkZW50JwpSYWRpYWxHbGlhJG9yaWcuaWRlbnQgPC0gJ1JhZGlhbEdsaWEnCgoKIyBkb3duc2FtcGxlIHRoZSBOZXVyb25zMiwgQXN0cm9jeXRlcyBhbmQgUmFkaWFsIEdsaWEKTmV1cm9uczIuc3ViIDwtIHN1YnNldChOZXVyb25zMiwgZG93bnNhbXBsZSA9IDIwMDApCk5ldXJvbnMyLnN1YgpJZGVudHMoTmV1cm9uczIuc3ViKSA8LSAnb3JpZy5pZGVudCcKQXN0cm8uc3ViIDwtIHN1YnNldChBc3Ryb2N5dGVzLCBkb3duc2FtcGxlID0gMjAwMCkKQXN0cm8uc3ViCklkZW50cyhBc3Ryby5zdWIpIDwtICdvcmlnLmlkZW50JwpSRy5zdWIgPC0gc3Vic2V0KFJhZGlhbEdsaWEsIGRvd25zYW1wbGUgPSAyMDAwKQpSRy5zdWIKSWRlbnRzKFJHLnN1YikgPC0gJ29yaWcuaWRlbnQnCnNvcnRlZC5tZXJnZSA8LSBtZXJnZShOZXVyb25zMSwgeT1jKE5ldXJvbnMyLnN1YixBc3Ryby5zdWIsUkcuc3ViKSwgYWRkLmNlbGwuaWRzID0gYygiTmV1cm9uczEiLCJOZXVyb25zMiIsIkFzdHJvY3l0ZXMiLCJSYWRpYWxHbGlhIiksIHByb2plY3QgPSAiU29ydGVkQ2VsbHMiKQpzb3J0ZWQubWVyZ2UKdW5pcXVlKHNvcnRlZC5tZXJnZSRvcmlnLmlkZW50KQoKc2F2ZVJEUyhzb3J0ZWQubWVyZ2UsICIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9zY1JOQXNlcS9QaGVub0lEL3NjUk5Bc2VxU29ydGVkL29ianMvbWVyZ2VkT2JqZWN0Tm92Mi5SZHMiKQoKCgpgYGAKCgpDbHVzdGVyIG1lcmdlIG9iamVjdCAKCmBgYHtyfQoKc2V1IDwtIHNvcnRlZC5tZXJnZQoKc2V1IDwtIE5vcm1hbGl6ZURhdGEoc2V1LCBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCBzY2FsZS5mYWN0b3IgPSAxMDAwMCkKc2V1IDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKHNldSwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpzZXUgPC0gU2NhbGVEYXRhKHNldSkKc2V1IDwtIFJ1blBDQShzZXUpCkVsYm93UGxvdChzZXUsIG5kaW1zID0gMzApCnNldSA8LSBSdW5VTUFQKHNldSwgZGltID0gMToxOCwgbi5uZWlnaGJvcnMgPSA0MykKRGltUGxvdChzZXUsIHJlZHVjdGlvbiA9ICJ1bWFwIikKCiMKCgoKYGBgCgoKUXVpY2sgYW5ub3RhdGlvbiBmcm9tIHByZXZpb3VzbHkgYW5ub3RhdGVkCgoKYGBge3J9CgphbmNob3JzIDwtIEZpbmRUcmFuc2ZlckFuY2hvcnMocmVmZXJlbmNlID0gc2V1LkwgLHF1ZXJ5ID0gc2V1LCBkaW1zID0gMToyNSkKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIHJlZmRhdGEgPSBzZXUuTCRDZWxsX1N1YnR5cGVfTWFya2VycykKc2V1IDwtIEFkZE1ldGFEYXRhKHNldSwgbWV0YWRhdGEgPSBwcmVkaWN0aW9ucyRwcmVkaWN0ZWQuaWQsIGNvbC5uYW1lID0gJ3ByZWRpY3RlZC5pZCcpCgpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5MJENlbGxfVHlwZXMpCnNldSA8LSBBZGRNZXRhRGF0YShzZXUsIG1ldGFkYXRhID0gcHJlZGljdGlvbnMkcHJlZGljdGVkLmlkLCBjb2wubmFtZSA9ICdwcmVkLkNlbGx0eXBlcycpCkRpbVBsb3Qoc2V1LCBncm91cC5ieSA9ICdwcmVkaWN0ZWQuaWQnKQpEaW1QbG90KHNldSwgZ3JvdXAuYnkgPSAncHJlZGljdGVkLmlkJywgc3BsaXQuYnkgPSAnb3JpZy5pZGVudCcpCgpEaW1QbG90KHNldSwgZ3JvdXAuYnkgPSAncHJlZC5DZWxsdHlwZXMnKQpEaW1QbG90KHNldSwgZ3JvdXAuYnkgPSAncHJlZC5DZWxsdHlwZXMnLCBzcGxpdC5ieSA9ICdvcmlnLmlkZW50JykKCgpgYGAKCk5PVEUgVE8gTUUgKioqKioqKiAKCkkgd2lsbCBuZWVkIHRvIGxvb2sgdGhyb3VnaCB0aGUgcHJlIC0gZmlsdGVyaW5nIGNlbGxzIC0gbmV1cm9ucyAxIGlzIHRoZSBzYW1lIAoKUG9zc2libGUganVzdCBkb3duIHNhbXBsZSBhc3RybyBzbyB0aGUgbnVtYmVycyBhcmUgdGhlIHNhbWUuIFRoZSBvdGhlciBzYW1wbGVzIHdlcmUgcmFuZG9tbHkgZG93bnNhbXBsZWQuICBNYXliZSBpZiBJIHJlcGVhdCB0aGUgZG93biBzYW1wbGluZyB3aXRoIGRpZmZlcmVudCBzZWVkcyBJJ2xsIGdldCByZXN1bHRzIG1vcmUgc2ltaWxhci4gIEFsc28gaWYgSSBjbHVzdGVyIGJlZm9yZSBkb3duIHNhbXBsaW5nIGxpa2UgSSBkaWQgdGhlIGZpcnN0IHRpbWUuICAKCgoKCgpgYGB7cn0KCgoKCgoKYGBgCgoKCgoKCgoKQ2FsY3VsYXRlIHByb3Byb3Rpb24gaW4gb2JqZWN0IGluIHRoZSBmaWd1cmVzOgoKYGBge3J9CgpwYXRod2F5IDwtICIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9zY1JOQXNlcS9QaGVub0lEL3NjUk5Bc2VxU29ydGVkL29ianMvIgpzZXUuTCA8LSByZWFkUkRTKHBhc3RlKHBhdGh3YXksICJDb21iaW5lZExhYmVsZWRNYXJrZXJzMTQxMDIwMjIuUkRTIikpCgpEaW1QbG90KHNldS5MLCBncm91cC5ieSA9ICdvcmlnLmlkZW50JykKCnRhYmxlKHNldS5MJG9yaWcuaWRlbnQpCgojIHN3aXRjaCBiYWNrIHRoZSBzd2l0Y2hlZCBOZXVyb25zCiMgcmVuYW1lCklkZW50cyhzZXUuTCkgPC0gJ29yaWcuaWRlbnQnCmNsdXN0ZXIuaWRzIDwtIGMoIk5ldXJvbnMxIiwgIk5ldXJvbnMyIiwgIkFzdHJvY3l0ZXMiLCJSYWRpYWxHbGlhIgogICAgICAgICAgICAgICAgICkKCgpuYW1lcyhjbHVzdGVyLmlkcykgPC0gbGV2ZWxzKHNldS5MKQpzZXUuTCA8LSBSZW5hbWVJZGVudHMoc2V1LkwsIGNsdXN0ZXIuaWRzKQpzZXUuTCRvcmlnLmlkZW50IDwtIElkZW50cyhzZXUuTCkKCgpzYXZlUkRTKHNldS5MLCBwYXN0ZShwYXRod2F5LCAiRmlndXJlT2JqZWN0MDIxMTIwMjIuUkRTIikpCgoKYGBgCgoKCmBgYHtyfQoKdGFibGUoc2V1Lkwkb3JpZy5pZGVudCwgc2V1LkwkQ2VsbF9UeXBlcykKdGFibGUoc2V1Lkwkb3JpZy5pZGVudCwgc2V1LkwkQ2VsbF9TdWJ0eXBlX01hcmtlcnMpCgpgYGAKCkZpZ3VyZSA2IEYKCmBgYHtyfQoKIyBtYWtlIHRoZSBiYXIgY2hhcnQgIHdpdGggdGhlIGNvcnJlY3QgY29sb3VycyAKCnNhbXBsZS5vcmRlciA8LSBjKCJBc3Ryb2N5dGVzLUNPTDNBMSIsIkFzdHJvY3l0ZXMtRkFCUDUiLCAiQXN0cm9jeXRlcy1IUEQiLAogICAgICAgICAgICAgICAgICAiREFOZXVyb25zLVJBQjNCIiwiREFOZXVyb25zLVRQQkciLCJEQU5ldXJvbnMtVFRSIiwKICAgICAgICAgICAgICAgICAgIk1peCIsIk5QQyIsCiAgICAgICAgICAgICAgICAgICJOZXVyb25zLUFTQ0wxIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtQ1AiLCJOZXVyb25zLUdSSUEyIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtTUdQIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtU1BBUkNMMSIsCiAgICAgICAgICAgICAgICAgICJOZXVyb25zLVRQSDEiLCAiTmV1cm9ucy1URlBJMSIsCiAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhLUNZMUIxIiwgIlJhZGlhbEdsaWEtTkVBVDEiLCJSYWRpYWxHbGlhLVBUTiIsCiAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhLVJQTDQxIiwgIlJhZGlhbEdsaWEtVE9QMkEiLCAiUmFkaWFsR2xpYS1WQ0FOIikKc2FtcGxlLm9yZGVyIDwtIHJldihzYW1wbGUub3JkZXIpCgoKY2x1c3QuY29sb3VycyA8LSBjKCIjRjFDMTY2IiwiI0ZGOTQwMCIsIiNFOTU5MDEiLCAgICAgICAgICAjIG9yYW5nZXMgQXN0cm9jeXRlcwogICAgICAgICAgICAgICAgICAgIiM0M0Q1OUMiLCIjN0RBNjk2IiwiIzE1QUUzNiIsICAgICAjIGdyZWVucyBEQSBuZXVyb25zCiAgICAgICAgICAgICAgICAgICAic3RlZWxibHVlIiwicmVkMiIsICAgIyBtaXggYW5kIE5QQwogICAgICAgICAgICAgICAgICAgIiM4RjY3RkYiLAogICAgICAgICAgICAgICAgICAgIiM2ODQwREIiLCIjOUI4QkM3IiwgICAjIG5ldXJvbnMgMiAgQ1AsIEdSSUEyCiAgICAgICAgICAgICAgICAgICAiIzdCMjJGQiIsICAgICMgTUdQCiAgICAgICAgICAgICAgICAgICAicHVycGxlIiwgIyBTUEFSQ0wxCiAgICAgICAgICAgICAgICAgICAiIzk4NjNFNSIsIiM4RTM2RDIiLCAjIFRQSDEsIFRGUEkxCiAgICAgICAgICAgICAgICAgICAiI0Y2OEQ4RCIsICMgUkcgQ1kxQjEKICAgICAgICAgICAgICAgICAgICIjRjY4ODg4IiwiI0Y2ODhCRCIsICAgIyBSRyBORUFUMSwgUFROIAogICAgICAgICAgICAgICAgICAgIiNGNTI4OEEiLCIjREM1N0NGIiwiI0YzQTZFQyIpCgoKCgpkZiA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldS5MJG9yaWcuaWRlbnQsIHNldS5MJENlbGxfU3VidHlwZV9NYXJrZXJzKSkKCiMgdGhlIGNoYXJ0IHdpbGwgZGVmYXVsdCB0byBhbHBoYWJldGljYWwKCgojIGJ1dCBub3QgZm9yIHRoZSB4IGF4aXMgLSByZW9yZGVyIHdpdGggZmFjdG9yIHRvIG1hdGNoIGZpZ3VyZSA2QQpkZiRGQUNwb3AgPC0gZmFjdG9yKGRmJFZhcjEsIGxldmVscyA9IGMoIkFzdHJvY3l0ZXMiLCJSYWRpYWxHbGlhIiwiTmV1cm9uczEiLCJOZXVyb25zMiIpKQpkZiRDZWxsX3N1YnR5cGVzIDwtIGZhY3RvcihkZiRWYXIyLCBsZXZlbHMgPSBzYW1wbGUub3JkZXIpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkJhckNoYXJ0UHJvcG9ydGlvbkNlbGxUeXBlc2luNHBvcHNOb3YyLnBkZiIpLCBoZWlnaHQgPSA1LCB3aWR0aCA9IDgpCmdncGxvdChkZiwgYWVzKHggPSBGQUNwb3AsIHkgPSBGcmVxLCBmaWxsID0gQ2VsbF9zdWJ0eXBlcykpICsgCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsgdGhlbWVfY2xhc3NpYygpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjbHVzdC5jb2xvdXJzKSArCiAgI3NjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gMTYpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArCiAgbGFicyh5ID0gIlByb3BvcnRpb24gb2YgQ2VsbHMiLCB4ID0gIiIpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpIApkZXYub2ZmKCkKCgoKCmBgYAoKCgoKCg==